/****************************************************************************************************/
/**
\file       SchM.c
\brief      Scheduler module main functionality of the scheduler
\date       08/03/2014
*/
/****************************************************************************************************/

 #include "SchM.h"
 #include "Mcu.h"
 #include "Gpt.h"
 

static u8 schM_counter;
static u8 schM_started=CNF_FALSE;
static u8 schM_OsTick_Changed;
static volatile SchM_TaskBlockControlType schm_task_status[CNF_TASKS_NUMBER];



/**************************************************************************************
* - Function      SchM_Init
* - Description   Function to init scheduler information, os tick and corresponding clocks.
* - Author        Equipo 1
* - Param         schM_Config Pointer with task information
* - Return        void
****************************************************************************************/
void SchM_Init(const SchM_TaskConfigType *schM_Config) 
{
  u8 taskIndex; 
  schM_counter = 0;
  for(taskIndex = 0; taskIndex< CNF_TASKS_NUMBER;  taskIndex++ ) 
  {
      schm_task_status[taskIndex].taskConfig.task_function = schM_Config->task_function;
      schm_task_status[taskIndex].taskConfig.mask = schM_Config->mask;
      schm_task_status[taskIndex].taskConfig.offset = schM_Config->offset;   
      schM_Config++;   
  }
  
  Mcu_Init(); /*Already done by Start12.c code */
  Mcu_InitClock();           /* Initialize PLL */
  Mcu_DistributePllClock();  /* Set PLL as source Clock */
  
  schM_OsTick_Changed = CNF_FALSE;
}
 
 
/**************************************************************************************
* - Function      SchM_DeInit
* - Description   Function to deinit scheduler and its os tick
* - Author        Equipo 1
* - Param         void
* - Return        void
****************************************************************************************/ 
void SchM_DeInit(void) 
{                  
     Gpt_DisableNotification(GPT_CHANNEL_0); /* Disable OS Tick callback */ 
     Gpt_StopTimer( GPT_CHANNEL_0);          /* Stop OS Tick timer */ 
     schM_started=CNF_FALSE;                 /* Clear flag toindicat Scheduler ha snot been started */
}


/**************************************************************************************
* - Function      SchM_Start
* - Description   Function to start scheduler and its os tick
* - Author        Equipo 1
* - Param         void
* - Return        void
****************************************************************************************/
void SchM_Start(void)
{
  Gpt_Init(&mcal_gpt_configuration);     /* Initialize Gpt driver */
  Gpt_StartTimer( GPT_CHANNEL_0);        /* Start Gpt Channel 0 */
  Gpt_EnableNotification(GPT_CHANNEL_0); /* Enable notifications of Channel 0 */
  
  /* Module wide flag to indicate Scheduler has started */
  schM_started = CNF_TRUE;   
}

/**************************************************************************************
* - Function      SchM_Background
* - Description   Function that must be running all time to execute corresponding task
* - Author        Equipo 1
* - Param         void
* - Return        void
****************************************************************************************/
void SchM_Background(void)
{
  u8 taskIndex; 
    
 /* Enter ONLY is scheduler has been started */ 
  if(CNF_TRUE ==schM_started  ) 
  {   
     /* Verify OS Tick has changedto avoid duplicated task execution */
     if( CNF_TRUE == schM_OsTick_Changed ) 
     {   
        /* Debug PIN for CPU load meaurement */
        PORTA_PA0 = 1; 
        /* Clear OS Tick changed flag */
        schM_OsTick_Changed = CNF_FALSE;                         
        /* Scan all tasks in teh task table  */
        for(taskIndex = 0; taskIndex< CNF_TASKS_NUMBER;  taskIndex++ ) 
        {
                  /* Execute corresponding task's callback based in his mask and offset */
                  if (schm_task_status[taskIndex].taskConfig.offset == (u8)(schM_counter & schm_task_status[taskIndex].taskConfig.mask)) 
                  {
                            schm_task_status[taskIndex].taskConfig.task_function(); 
                  }

        }
        /* Debug PIN for CPU load meaurement */
        PORTA_PA0 = 0;
     }
     
  }
  
}


/**************************************************************************************
* - Function      SchM_OsTick
* - Description   Function used as OS tick to enable tasks according to its mask and offset
* - Author        Equipo 1
* - Param         void
* - Return        void
****************************************************************************************/
void SchM_OsTick(void)
{
  if(CNF_TRUE ==schM_started  ) 
  {
    /* Increase OS Tick counter */
    schM_counter++;
    /* Set OS Tick changed Flag */
    schM_OsTick_Changed = CNF_TRUE; 
    /* Debu pin to measure OS Tick period */
    PORTB_PB0 ^= 1; 
  } 
}

